/*
 * ========================================================================
 *
 *       Filename:  deck.h
 *
 *    Description:  This defines the deck class.
 *
 *        Version:  1.0
 *        Created:  05/10/2010 04:28:59 PM
 *       Revision:  none
 *       Compiler:  g++
 *
 *         Author:  Alex Avance (aa), aravance@gmail.com
 *        Company:  independent
 *
 * ========================================================================
 *
 * Copyright (C) 2010 Alex Avance
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-
 * 1307, USA.
 *
 * ========================================================================
 */
#ifndef _DECK_H_
#define _DECK_H_

#include "card.h"
#include "statinfo.h"
#include <deque>

/**************************************************************************
Class Name: StudyDeck
Description: This defines a deck of cards. Within the deck, there are the
             following functions:
               Begin       - return iterator to first element
               End         - return iterator to one past last element
               RBegin      - return reverse iterator to last
               REnd        - return reverse iterator to one past first
               At          - access element at position
               Top         - return the top element
               Bottom      - return the bottom element
               Size        - return the number of elements
               Count       - return the number of elements
               Empty       - true if empty
               Pop         - remove top element
               Push        - push element to the top
               Next        - cycle one element forward
               Prev        - cycle one element backward
               Clear       - empty out the deck
               Assign      - assign deck contents
               Append      - append elements to the deck
               Insert      - insert elements into the deck
               Erase       - remove elements from the deck
               Sort        - sort the deck
               Shuffle     - shuffle the deck
               operator[]  - access element at position
               operator=   - assign deck contents
             Note: every function has a lowercase equivalent
**************************************************************************/
class StudyDeck: public StatInfo
{
public:
  typedef StudyCard CardT;
  typedef std::deque<CardT> DeckT;

  typedef DeckT::iterator iterator;
  typedef DeckT::const_iterator const_iterator;
  typedef DeckT::reverse_iterator reverse_iterator;
  typedef DeckT::const_reverse_iterator const_reverse_iterator;

  typedef CardT::InfoT InfoT;
  typedef StatInfo::StatT StatT;

  // ====================  LIFECYCLE     ================================
  StudyDeck ();
  StudyDeck ( const StudyDeck &other );
  StudyDeck ( const DeckT &deck );
  virtual ~StudyDeck ();

  // ====================  ACCESSORS     ================================
  iterator Begin ();
  const_iterator Begin () const;
  iterator End ();
  const_iterator End () const;

  reverse_iterator RBegin ();
  const_reverse_iterator RBegin () const;
  reverse_iterator REnd ();
  const_reverse_iterator REnd () const;

  CardT& At ( size_t pos );
  const CardT& At ( size_t pos ) const;

  CardT& Top ();
  const CardT& Top () const;

  CardT& Bottom ();
  const CardT& Bottom () const;

  size_t Size () const;
  size_t Count () const;

  bool Empty () const;

  // ====================  MUTATORS      ================================
  void Pop ();

  void Push ( const CardT &card );
  void Push ( const InfoT &front, const InfoT &back,
              StatT right= 0, StatT wrong= 0 );

  void Next ();
  void Prev ();

  void Clear ();

  const StudyDeck& Assign ( const StudyDeck &other );
  const StudyDeck& Assign ( const DeckT &deck );
  template <class InputIterator>
  const StudyDeck& Assign ( InputIterator start, InputIterator stop )
  {
    m_Container.assign( start, stop );
    return *this;
  }

  const StudyDeck& Append ( const StudyDeck &other );
  const StudyDeck& Append ( const DeckT &deck );
  const StudyDeck& Append ( const CardT &card );
  const StudyDeck& Append ( const InfoT &front, const InfoT &back,
                            StatT right= 0, StatT wrong= 0 );
  template <class InputIterator>
  const StudyDeck& Append ( InputIterator start, InputIterator stop )
  {
    m_Container.insert( end(), start, stop );
    return *this;
  }

  void Insert ( iterator pos, const StudyDeck &other );
  void Insert ( size_t pos, const StudyDeck &other );
  void Insert ( iterator pos, const DeckT &deck );
  void Insert ( size_t pos, const DeckT &deck );
  void Insert ( iterator pos, const CardT &card );
  void Insert ( size_t pos, const CardT &card );
  template <class InputIterator>
  void Insert ( iterator pos, InputIterator start, InputIterator stop )
  { m_Container.insert( pos, start, stop ); }
  template <class InputIterator>
  void Insert ( size_t pos, InputIterator start, InputIterator stop )
  { m_Container.insert( m_Container.begin() + pos, start, stop ); }

  void Erase ( iterator start, iterator stop );
  void Erase ( iterator pos );
  void Erase ( size_t pos );

  virtual void Sort ();

  virtual void Shuffle ();

  virtual void Guess ( bool result );
  virtual void ResetStats ();
  virtual void RecountStats ();

  // ====================  OPERATORS     ================================
  StudyDeck& operator= ( const StudyDeck &other );
  StudyDeck& operator= ( const DeckT &deck );
  CardT& operator[] ( size_t pos );
  const CardT& operator[] ( size_t pos ) const;

  // ====================  DATA MEMBERS  ================================
protected:
  DeckT m_Container;

  virtual void m_Sort ( iterator left, iterator right );

  // ====================  LOWERCASE VARIATIONS =========================
public:
  iterator begin ();
  const_iterator begin () const;
  iterator end ();
  const_iterator end () const;
  reverse_iterator rbegin ();
  const_reverse_iterator rbegin () const;
  reverse_iterator rend ();
  const_reverse_iterator rend () const;
  CardT& at ( size_t pos );
  const CardT& at ( size_t pos ) const;
  CardT& top ();
  const CardT& top () const;
  CardT& bottom ();
  const CardT& bottom () const;
  size_t size () const;
  size_t count () const;
  bool empty () const;
  void pop ();
  void push ( const CardT &card );
  void push ( const InfoT &front, const InfoT &back,
              StatT right= 0, StatT wrong= 0 );
  void next ();
  void prev ();
  void clear ();
  const StudyDeck& assign ( const StudyDeck &other );
  const StudyDeck& assign ( const DeckT &deck );
  template <class InputIterator>
  const StudyDeck& assign ( InputIterator start, InputIterator stop )
  { return Assign( start, stop ); }
  const StudyDeck& append ( const StudyDeck &other );
  const StudyDeck& append ( const DeckT &deck );
  const StudyDeck& append ( const CardT &card );
  const StudyDeck& append ( const InfoT &front, const InfoT &back,
                            StatT right= 0, StatT wrong= 0 );
  template <class InputIterator>
  const StudyDeck& append ( InputIterator start, InputIterator stop )
  { return Append( start, stop ); }
  void insert ( iterator pos, const StudyDeck &other );
  void insert ( size_t pos, const StudyDeck &other );
  void insert ( iterator pos, const DeckT &deck );
  void insert ( size_t pos, const DeckT &deck );
  void insert ( iterator pos, const CardT &card );
  void insert ( size_t pos, const CardT &card );
  template <class InputIterator>
  void insert ( iterator pos, InputIterator start, InputIterator stop )
  { m_Container.insert( pos, start, stop ); }
  template <class InputIterator>
  void insert ( size_t pos, InputIterator start, InputIterator stop )
  { m_Container.insert( m_Container.begin() + pos, start, stop ); }
  void erase ( iterator start, iterator stop );
  void erase ( iterator pos );
  void erase ( size_t pos );
  virtual void sort ();
  virtual void shuffle ();
  virtual void guess ( bool result );
  virtual void resetstats ();
  virtual void recountstats ();
}; // ----- end of class StudyDeck -----

#endif // _DECK_H_

